#ifndef __GTEST_4_C_H__
#define __GTEST_4_C_H__

#ifdef __cplusplus

	#include <gtest/gtest.h>

	#define GTEST_EXTERN_C_BEGIN  extern"C" {
	#define GTEST_EXTERN_C_END    }
	#define GTEST_EXTERN_C extern "C"

#else

#define GTEST_EXTERN_C_BEGIN
#define GTEST_EXTERN_C_END
#define GTEST_EXTERN_C

#endif

typedef struct gtest_case_def
{
	const char* suiteName;
	const char* caseName;
	void (*func)();
}GTEST_CASE_DEF;

GTEST_EXTERN_C void gtest_assert_success ();
GTEST_EXTERN_C void gtest_assert_failure (const char* file,int nLine,const char* s);
GTEST_EXTERN_C void gtest_init (int* argc, char** argv);
GTEST_EXTERN_C int  gtest_run ();
GTEST_EXTERN_C void gtest_register (struct gtest_case_def* list);

#define C_TEST_CASE_BEGIN(nm) struct gtest_case_def nm[] = {
#define C_TEST_CASE(testSuite,testCase) {#testSuite, #testCase, tcase_##testSuite##_##testCase },
#define C_TEST_CASE_END()   {NULL, NULL, NULL} };

#define C_TEST(testSuite,testCase) void tcase_##testSuite##_##testCase()
#define C_TEST_R(testSuite,testCase) void tcase_##testSuite##_##testCase(){};void tcase_##testSuite##_##testCase##_remove()
#define C_ASSERT_TRUE_EX(b,ret) do { if (!(b)) { gtest_assert_failure(__FILE__,__LINE__,#b); return ret; } } while(0)
#define C_ASSERT_TRUE(b)        do { if (!(b)) { gtest_assert_failure(__FILE__,__LINE__,#b); return; } } while(0)

#ifdef C_TEST_IMPL

GTEST_EXTERN_C void gtest_assert_success()
{
	testing::AssertionSuccess();
};

GTEST_EXTERN_C void gtest_assert_failure(const char* file,int nLine,const char* s)
{
	::testing::internal::AssertHelper(::testing::TPRT_FATAL_FAILURE, file, nLine,s) = ::testing::Message();
}

class gtest_test_case : public testing::Test {
public:
	 gtest_test_case ( void (*func)() ) : _f(func) {};
private:
	 virtual void TestBody() { _f(); };
	 void (*_f)();
};

class gtest_test_case_factory : public testing::internal::TestFactoryBase {
 public:
	gtest_test_case_factory( void(*func)() ) :_f(func){};
	virtual testing::Test* CreateTest() { return new gtest_test_case(_f); }
	void (*_f)();
};

GTEST_EXTERN_C void gtest_register (struct gtest_case_def* list)
{
	for (;list->func; list++)
	{
		testing::internal::MakeAndRegisterTestInfo(
			list->suiteName,
			list->caseName, 
			"",
			"", 
			::testing::internal::GetTestTypeId(), 
			testing::Test::SetUpTestCase,
			testing::Test::TearDownTestCase,
			new gtest_test_case_factory(list->func)
		);
	}
}

GTEST_EXTERN_C void gtest_init(int* argc, char** argv)
{
	testing::InitGoogleTest (argc, argv);
}

GTEST_EXTERN_C int gtest_run()
{
	return RUN_ALL_TESTS();
}

#endif

#endif
